import re
from contextlib import closing

import re
import time
from contextlib import closing

import requests
from flask import Flask, request, Response
from werkzeug.datastructures import ImmutableMultiDict

from core.config import LISTEN_PORT, GOAL_PORT, GOAL_URL
from core.documents import Ask

app = Flask(__name__)


@app.before_request
def before_request():
    from core.documents import AskProxySetting
    url = request.url
    method = request.method
    data = request.form or request.data or None
    if data and isinstance(data, ImmutableMultiDict):  # 支持传输列表
        td = {}
        for key in data:
            if len(data.getlist(key)) > 1:
                td[key] = data.getlist(key)
            else:
                td[key] = data[key]
        data = td
    headers = dict()
    goalurl = re.sub("://(.*?)/", "://{}:{}/".format(GOAL_URL, GOAL_PORT), url)
    for name, value in request.headers:
        if name == 'Content-Type':
            if 'form-data' in value:
                continue
        headers[name] = value
    ask = Ask(url=goalurl, method=method, data=data, headers=headers, source_type='原始请求')
    files = {}
    for k in request.files:
        files[k] = (request.files[k].filename, request.files[k], request.files[k].content_type)
        request.files[k].seek(0)
    with closing(
            requests.request(method, goalurl, headers=headers, data=data,
                             files=files,
                             allow_redirects=False)
    ) as r:
        resp_headers = []
        for name, value in r.raw.headers.items():
            resp_headers.append((name, value))
        if AskProxySetting.is_on_listen():
            ask.date = int(time.time())
            ask.resp_content = r.content
            ask.resp_header = resp_headers
            ask.resp_stat = r.status_code
            ask.hash_code = ask.make_key()
            ask.has_file = len(request.files) > 0
            try:
                import json
                json.loads(r.content.decode())
                ask.save()
            except Exception:
                pass
        return Response(r, status=r.status_code, headers=resp_headers)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=LISTEN_PORT, debug=False)
